using MapMaker.VirtualEarth;
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace MapMaker
{
    [ComVisible(true)]
    public partial class frmMap : Form
    {
		private frmMain parentForm = null;
        private delegate void DownloadCompleteDelegate();
        private delegate void PackageCompleteDelegate();

        private ArrayList route = null;
        private string routeDistance = null;
        private string routeTime = null;
        private string zoomLevel = null;
        private int pixelCenterX;
        private int pixelCenterY;
        private double latitude;
        private double longitude;

        private bool startPackaging = true;

        public frmMap()
        {
            InitializeComponent();
            webMapBrowser.Width = 640;
            webMapBrowser.Height = 640;
            webMapBrowser.ObjectForScripting = this;
            webMapBrowser.Navigate(Path.Combine(Application.StartupPath, "map.htm"));
            cboViewType.SelectedIndex = 0;
        }

        public WebBrowser Browser
        {
            get
            {
                return webMapBrowser;
            }
        }

        public ArrayList Route
        {
            get
            {
                return route;
            }
        }

        public string RouteDistance
        {
            get
            {
                return routeDistance;
            }
        }

        public string RouteTime
        {
            get
            {
                return routeTime;
            }
        }

        public void MapLoaded()
        {
        }

        public void RouteLoaded(string distance, string time, string directions)
        {
            if (!string.IsNullOrEmpty(directions))
            {
                routeDistance = distance;
                routeTime = time;

                route = new ArrayList();

                foreach (string line in directions.Split((new string[] {"\r\n"}), StringSplitOptions.RemoveEmptyEntries))
                {
                    route.Add(line.Split(new char[] { '|' }));
                }

				((frmMain)this.MdiParent).DirectionsForm.Route = route;
				((frmMain)this.MdiParent).DirectionsForm.TotalDistance = distance;
				((frmMain)this.MdiParent).DirectionsForm.TotalTime = time;
				((frmMain)this.MdiParent).DirectionsForm.Show();
            }
        }

        public void SetCenterCoords(string latitude, string longitude, string zoom)
        {
            zoomLevel = zoom;
            this.latitude = double.Parse(latitude);
            this.longitude = double.Parse(longitude);

            VirtualEarthTileSystem.LatLongToPixelXY(double.Parse(latitude), double.Parse(longitude), int.Parse(zoomLevel), out pixelCenterX, out pixelCenterY);
        }

        private void frmMap_Load(object sender, EventArgs e)
        {
			parentForm = (frmMain)this.MdiParent;
        }

        public void GetDirections(string start, string end, string unit, string type)
        {
            webMapBrowser.Document.InvokeScript("GetRoute", new object[] { start, end, unit, type });
        }

        private void tsbSaveMap_Click(object sender, EventArgs e)
        {
            VirtualEarthTileAccess.MapType mapType;
            
            Program.TileAccess = new VirtualEarthTileAccess();
            Program.TileAccess.GotFile += new VirtualEarthTileAccess.GotFileHandler(TileAccess_OnGotFile);
            Program.TileAccess.GotMap += new VirtualEarthTileAccess.GotMapHandler(TileAccess_OnGotMap);

            switch (cboViewType.SelectedItem.ToString().ToLower())
            {
                case "road":
                    mapType = VirtualEarthTileAccess.MapType.Road;
                    break;
                case "hybrid":
                    mapType = VirtualEarthTileAccess.MapType.Hybrid;
                    break;
                case "aerial":
                    mapType = VirtualEarthTileAccess.MapType.Aerial;
                    break;
                default:
                    mapType = VirtualEarthTileAccess.MapType.Road;
                    break;
            }

            frmDownloadOptions optionsForm = new frmDownloadOptions(Program.TileAccess, pixelCenterX, pixelCenterY, int.Parse(zoomLevel), mapType);
            DialogResult result = optionsForm.ShowDialog(this.MdiParent);

            if (result == DialogResult.OK)
            {
                startPackaging = false;

                parentForm.ProgressForm = new frmProgress();

                parentForm.ProgressForm.LowerBound = 0;

                int tileCount = Program.TileAccess.GetTileCount(pixelCenterX, pixelCenterY, int.Parse(zoomLevel), mapType);
                parentForm.ProgressForm.UpperBound = tileCount;

                Program.TileAccess.DownloadTiles(pixelCenterX, pixelCenterY, int.Parse(zoomLevel), mapType);

                parentForm.ProgressForm.Status = "Downloading Tiles...";
                parentForm.ProgressForm.ShowDialog(this);
            }
        }

        private void TileAccess_OnGotFile(int numCompleted)
        {
            parentForm.ProgressForm.Status = "Downloading Tiles: " +
                numCompleted + " of " + parentForm.ProgressForm.UpperBound + " received.";
            parentForm.ProgressForm.SetProgress(numCompleted);
        }

        private void MapPackage_OnTileInserted(int numInserted)
        {
            parentForm.ProgressForm.Status = "Packaging Tiles: " +
                numInserted + " of " + parentForm.ProgressForm.UpperBound + " completed.";
            parentForm.ProgressForm.SetProgress(numInserted);
        }

        private void MapPackage_OnPackageComplete()
        {
            if (parentForm.ProgressForm.InvokeRequired)
            {
                PackageCompleteDelegate d = new PackageCompleteDelegate(MapPackage_OnPackageComplete);
                this.Invoke(d);
            }
            else
            {
                parentForm.ProgressForm.Close();
                MessageBox.Show("Map download and packaging complete.");
                startPackaging = true;
            }
        }

        private void cboViewType_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            string mapStyle =  null;

            switch(cboViewType.SelectedItem.ToString().ToLower())
            {
                case "road":
                    mapStyle = "r";
                    break;
                case "hybrid":
                    mapStyle = "h";
                    break;
                case "aerial":
                    mapStyle = "a";
                    break;
            }

            if (!string.IsNullOrEmpty(mapStyle))
            {
                webMapBrowser.Document.InvokeScript("SetMapStyle", new object[] {mapStyle});
            }
        }

        private void TileAccess_OnGotMap()
        {
            downloadComplete();
        }

        private void downloadComplete()
        {
            if (parentForm.ProgressForm.InvokeRequired)
            {
                DownloadCompleteDelegate d = new DownloadCompleteDelegate(downloadComplete);
                this.Invoke(d);
            }
            else
            {
                if (!startPackaging)
                {
                    startPackaging = true;
                }
                else
                {
                    parentForm.ProgressForm.SetProgress(0);
                    parentForm.ProgressForm.Status = "";

                    MapPackage package = new MapPackage(Program.TileAccess.MapName, Program.TileAccess.SaveDirectory, longitude, latitude);

                    package.TileInserted += new MapPackage.TileInsertedHandler(MapPackage_OnTileInserted);
                    package.PackageComplete += new MapPackage.PackageCompleteHandler(MapPackage_OnPackageComplete);

                    package.CreatePackage();
                }
            }
        }
    }
}